<?php
namespace app\common\model;
use Redis;
use think\facade\Cache;
use think\Model;
use think\Validate;
class BaseModel extends Model
{

    public static $fields_status = [
        ['name'=>'--',''],
        ['name'=>'正常'],
        ['name'=>'禁用'],
    ];

    protected static $fields_type_cache_str = "";
    protected static $fields_type = [];

    protected $jsonAssoc  = true;




    public function getCreateDateAttr($value,array $data=[])
    {
        return empty($data['create_time'])?'':date('Y-m-d',$data['create_time']);
    }

    public function getUpdateDateAttr($value,array $data=[])
    {
        return empty($data['update_time'])?'':date('Y-m-d',$data['update_time']);
    }


    protected $step_flow=[];

    /**
     * @var Redis|null
     * */
    private static $_redis = null;

    /**
     * 获取redis单例
     * @return Redis
     * */
    public static function getRedisInstance()
    {
        if(empty(self::$_redis)){
            self::$_redis = Cache::store('redis')->handler();
        }
        return self::$_redis;
    }

    /**
     * 订单流程
     * @param int|null $step 流程步骤
     * @param string|null $need_field 需要字段
     * @param string $def_attr 流程对应字段属性
     * @return array|string|
     * */
    public function getStepFlowInfo($step=null, $need_field='name', $def_attr='prop_func')
    {
        if(method_exists($this,'step_flow')){
            $data = $this->step_flow();
        }else{
            $data = $this->step_flow;
        }

        if(is_null($step)){
            return $data;
        }else{
            if(!isset($data[$step])){
                return;
            }
            //流程信息
            $info = $data[$step];
            if($def_attr=='prop_func'){
                return self::getPropInfo($info[$def_attr],$this->getAttr($info['field']),$need_field);
            }else{
                return is_null($def_attr)?$info:(isset($info[$need_field])?$info[$need_field]:'');
            }
        }
    }


    /**
     * 获取用户对订单可执行的操作
     * @param string  $mode 操作人员 u_handle|m_handle
     * @param BaseModel  $user_model 操作对象
     * @return array
     * */
    public function getHandleAction(array $flow_handle)
    {
        //可操作流程
        $attr_data = $this->getData();
        $handle = [];
        if(!empty($flow_handle) && is_array($flow_handle)){
            foreach ($flow_handle as $index=>$fh){
                if(is_array($fh)){
                    //条件
                    $temp_bool = true;
                    foreach ($fh as $cond_key=>$cond_val){
                        if(isset($attr_data[$cond_key])){
                            if(is_array($cond_val)){
                                $cond=$cond_val[0];
                                $val=$cond_val[1];
                                $is_sure = false;
                                switch ($cond){
                                    case '==':
                                        if($attr_data[$cond_key]==$val){
                                            $is_sure= true;
                                        }
                                        break;
                                    case '>':
                                        if($attr_data[$cond_key]>$val){
                                            $is_sure= true;
                                        }
                                        break;
                                    case '>=':
                                        if($attr_data[$cond_key]>=$val){
                                            $is_sure= true;
                                        }
                                        break;
                                    case '<':
                                        if($attr_data[$cond_key]<$val){
                                            $is_sure= true;
                                        }
                                        break;
                                    case '<=':
                                        if($attr_data[$cond_key]<=$val){
                                            $is_sure= true;
                                        }
                                        break;
                                    case '!=':
                                        if($attr_data[$cond_key]!=$val){
                                            $is_sure= true;
                                        }
                                        break;
                                    default:
                                        break;
                                }
                                if(!$is_sure){
                                    $temp_bool = false;
                                    break;
//                                    array_push($handle,$index);
                                }
                            }elseif( $attr_data[$cond_key]!=$cond_val){
                                $temp_bool = false;
                                break;

                            }
                        }
                    }
                    $temp_bool && array_push($handle,$index);
                }elseif(is_callable($fh)){
                    if($fh($this,$user_model)){
                        array_push($handle,$index);

                    }
                }else{
                    is_string($fh) && array_push($handle,$fh);
                }
            }
        }
//        exit;
        return $handle;
    }






    //状态
    public static function getPropInfo($propOrFunc,$key=null,$field=null,$point_field=null)
    {
        $class = get_called_class();
        if(method_exists($class,$propOrFunc)){
            $data = $class::$propOrFunc();
        }elseif(property_exists($class,$propOrFunc)){
            $data = $class::$$propOrFunc;
        }else{
            return false;
        }
        if(is_null($key) && is_null($field)){
            return is_null($field)?$data:false;
        }else{
            $info=[];
            if(is_null($point_field)){
                $info = isset($data[$key])?$data[$key] : [];
            }else{
                foreach ($data as $vo){
                    if(isset($vo[$point_field]) && $vo[$point_field]==$key){
                        $info = $vo;
                        break;
                    }
                }
            }
            return is_null($field)?$info:(isset($info[$field])?$info[$field]:'');
        }
    }

    /**
     * 数据保存/更新
     * @param array $data 数据
     * @param \think\Validate $validate 验证器
     * @param \Closure $func 闭包
     * @throws
     * @return self;
     * */
    public function actionAdd(array $data=[],Validate $validate=null)
    {
        if ($validate && !$validate->check($data)) {
            throw new \Exception($validate->getError());
        }
        $model = $this;
        $pk = $this->getPk();
        if(!empty($data[$pk])){  //编辑状态
            $model = $this->find($data[$pk]);
        }else{
            //清除主键影响
            unset($data[$pk]);
        }

        $model && $model->save($data);
        return $model;

    }






    /**
     * 数据删除
     * @param array  $where 条件
     * @throws
     * */
    public static function actionDel(array $where=[])
    {
        if(!count($where)) throw new \Exception('条件异常');
        $model = static::where($where)->find();
        $model && $model->delete();
    }
    /**
     * 调整数据
     * @param $input_data array
     * @throws
     * */
    public static function modInfo(array $input_data=[],array $where = [])
    {
        if($where){
            $model = static::where($where)->find();
        }else{
            if(empty($input_data['id'])) throw new \Exception('参数异常:id');
            $model = static::find($input_data['id']);
        }
        if(empty($model)) throw new \Exception('操作对象不存在');
        $model->save($input_data);
    }




    // 制作邀请码
    public static function make_coupon_card() {
        $code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
        $rand = $code[rand(0,25)]
            .strtoupper(dechex(date('m')))
            .date('d').substr(time(),-5)
            .substr(microtime(),2,5)
            .sprintf('%02d',rand(0,99));
        for(
            $a = md5( $rand, true ),
            $s = '0123456789ABCDEFGHIJKLMNOPQRSTUV',
            $d = '',
            $f = 0;
            $f < 8;
            $g = ord( $a[ $f ] ),
            $d .= $s[ ( $g ^ ord( $a[ $f + 8 ] ) ) - $g & 0x1F ],
            $f++
        );
        return  $d;
    }



    //订单号 01-订单 90-退款
    protected static function getDateNo($order_type)
    {
        $cache_name = 'order_no'.$order_type.date('Y-m-d');
        $number = cache($cache_name);
        empty($number) && $number = 0;
        $number+=1;
        //保存一天时间
        cache($cache_name,$number,86400);
        $number = sprintf('%03d',$number);
        return date('Ymds').rand(10,99).sprintf('%02d',$order_type).$number;
    }

//    //生成唯一数字
//    public static function generateNumber($type)
//    {
//        $date = date('Y-m-d');
//        $model = Db::table('_generate')->where(['type'=>$type,'date'=>$date])->find();
//        $number = $model['number']??0;
//        if(is_null($model)){
//            //创建数据
//            DB::table('_generate')->insert(['type'=>$type,'date'=>$date,'number'=>$number]);
//        }
//        //影响行数
//        $row_num = DB::table('_generate')
//            ->where(['type'=>$type,'date'=>$date,'number'=>$number])
//            ->update(['number'=>Db::raw('number+1')]);
//        if(empty($row_num)){
//            $number = self::generateNumber($type);
//        }
//        return $number;
//    }
    public static function generateNumber($type)
    {
        $cache_name = date('Y-m-d').'generateNumber' . $type;
        $number = cache($cache_name);
        empty($number) && $number = 0;
        $number += 1;
        //保存一天时间
        cache($cache_name, $number, 86400);
        return $number;
    }

    //组合号码
    public static function generateNumberGroup($type,$len=3)
    {
        $number = static::generateNumber($type);
        return date('Ymds').sprintf('%03d',mt_rand(1,100)).sprintf('%0'.$len.'d',$number);
    }

    /**
     * 生成user_token
     * @return string
     * */
    public function generateUserToken($password,$type="00")
    {
        $time = time();
        $access_token = $type.'.'.$this->id.'.'.$time.'.'.self::generateSign($type, $this->id,$time).'.'.self::generateSecPwd($type,$password,$time);
//        dump($password,self::generateSecPwd($type,$password,$time));exit;
        //更新登录凭证
        // $this->token = $access_token;
        // $this->save();
        return $access_token;
    }

    /**
     * 验证user_token
     * @param string $user_token
     * @return bool|array
     * */
    public static function validUserToken($user_token)
    {
        if(empty($user_token)){
            return false;
        }
        $arr = explode('.',$user_token);
        $arr_len = count($arr);
        if($arr_len!=5){
            return false;
        }
        if($arr[3] !=self::generateSign($arr[0],$arr[1],$arr[2])){
            return false;
        }
        return $arr;

    }

    /**
     * 验证user_token
     * @param string $user_token
     * @return bool|array
     * */
    public static function validSecPwd($password, $user_token)
    {
        if(empty($user_token)){
            return false;
        }
        $arr = explode('.',$user_token);
        $arr_len = count($arr);
        if($arr_len!=5){
            return false;
        }
//        dump($arr,$password,self::generateSecPwd($arr[0],$password,$arr[2]));exit;
        if($arr[4] != self::generateSecPwd($arr[0],$password,$arr[2])){
            return false;
        }
        return $arr;

    }


    //生成token签名
    protected static function generateSign($type,$user_id,$time)
    {
        return md5($type.$user_id.md5($time));
    }

    //生成密码签名
    protected static function generateSecPwd($type,$password,$time)
    {
        return md5($type.$password.md5($time));
    }



    /**
     * 密码加密
     * @param string $password 输入密码
     * @param string $salt 密码盐
     * @return string
     * */
    public static function generatePwd($password, $salt)
    {
        return openssl_encrypt(self::_pwd_plus_code($password), 'DES-ECB', trim($salt));
    }

    /**
     * 密码解密
     * @param string $password 输入密码
     * @param string $salt 密码盐
     * @return string
     * */
    public static function de_generatePwd($password, $salt)
    {
        return openssl_decrypt($password, 'DES-ECB', trim($salt));
    }

    private static function _pwd_plus_code($pwd)
    {
        return '!@#123:;'.$pwd.';:321#@!';
    }

    public function apiFullInfo()
    {
        //获取数据库模型
        $db_fields = $this->checkAllowFields();
        $normalInfo = $this->apiNormalInfo();
        $data = [];
        foreach ($db_fields as $field){
            if(array_key_exists($field,$normalInfo)) continue;
            $data[$field] = $this[$field];
        }
        return array_merge($this->apiNormalInfo(),$data);
    }
    public function apiNormalInfo()
    {
        return [];
    }

}